home *** CD-ROM | disk | FTP | other *** search
/ NeXT Enterprise Objects Framework 1.1 / NeXT Enterprise Objects Framework 1.1.iso / NextDeveloper / Examples / EnterpriseObjects / MasteringDetails / EOFExtensions.subproj / ResetRelationships.m < prev    next >
Encoding:
Text File  |  1995-02-18  |  4.7 KB  |  120 lines

  1. /* ResetRelationships.m created by cfeder on Thu 15-Dec-1994 */
  2.  
  3. #import "ResetRelationships.h"
  4. #import "ValueForKey.h"
  5. #import "RelationshipKeySetter.h"
  6.  
  7. @implementation EODatabaseChannel (setForeignKey)
  8. - objectForPrimaryKey:(NSDictionary *)key entity:(EOEntity *)entity
  9.     // returns existing object instance if there is one, or a fault otherwise
  10. {
  11.     EODatabaseContext *context = [self databaseContext];
  12.     id object = [context objectForPrimaryKey:key entity:entity];
  13.     if (!object) {
  14.         object = [EOFault objectFaultWithPrimaryKey:key
  15.             entity:entity databaseChannel:self zone:[self zone]];
  16.     }
  17.     return object;
  18. }
  19.  
  20. - fetchObjectDescribedByQualifier:(EOQualifier *)qualifier
  21.     // raises if not to-one.
  22. {
  23.     BOOL success, autoTransaction = NO;
  24.     EODatabaseContext *context = [self databaseContext];
  25.     NSZone *zone = [self zone];
  26.     id object;
  27.  
  28.     if (![context transactionNestingLevel]) {
  29.         [context beginTransaction];
  30.         autoTransaction = YES;
  31.     }
  32.  
  33.     success = [self selectObjectsDescribedByQualifier:qualifier
  34.         fetchOrder:nil];
  35.     object = [self fetchWithZone:zone];
  36.     if (!success || !object || [self fetchWithZone:zone]) {
  37.         [self cancelFetch];
  38.         [NSException raise:NSInternalInconsistencyException format:@"%s: error fetching object", sel_getName(_cmd)];
  39.     }
  40.  
  41.     if (autoTransaction) [context commitTransaction];
  42.     return object;
  43. }
  44.  
  45. - destinationObjectForRelationship:relationship sourceObject:sourceObject
  46.     // look up an exising fault, or create a new one
  47. {
  48.     id object;
  49.     // EODatabase *database = [[self databaseContext] database];
  50.  
  51.     if ([relationship isToMany]) {
  52.         // EOF doesn't unique faults, so we just have to construct a new one
  53.         EOQualifier *qual = [EOQualifier qualifierForObject:sourceObject relationship:relationship];
  54.         object = [EOFault arrayFaultWithQualifier:qual
  55.             fetchOrder:nil databaseChannel:self zone:[self zone]];
  56.     } else {
  57.         // see if this is already in the uniquing table
  58.         if ([relationship isFlattened]) {
  59.             EOQualifier *qual = [EOQualifier qualifierForObject:sourceObject relationship:relationship];
  60.  
  61.             // should fetch object from channel with qualifier
  62.             object = [self fetchObjectDescribedByQualifier:qual];
  63.         } else {
  64.             // for to-ones, the primary key is always the destination of the
  65.             // relationship
  66.             NSDictionary *pk = [relationship destinationValuesFromSourceObject:sourceObject];
  67.             object = [self objectForPrimaryKey:pk entity:[relationship destinationEntity]];
  68.         }
  69.     }
  70.     return object;
  71. }
  72.  
  73. - (void)updateRelationshipsInObject:object forModifiedAttributes:(NSArray *)attributes
  74.    // After the values in object corresponding to the EOAttributes
  75.    // in the "attributes" array have been update (perhaps with 
  76.    // takeValuesFromDictionary) this method can be called to update any
  77.    // corresponding relationship properties.  So, if a foreign dept_id
  78.    // attribute way modified in a employee object, this would attempt to
  79.    // reset the "toDepartment" property to point at the corresponding
  80.    // department object.
  81. {
  82.     // We should apply some caching here to make this fast.  I.e. map directly
  83.     // from attribute to list of class property relationships that this participates in.
  84.     // For now we'll just be simple and slow.
  85.     NSMutableArray *affectedRelationships = [NSMutableArray array];
  86.     EOModel *model = [[[[self databaseContext] database] adaptor] model];
  87.     EOEntity *entity = [model entityForObject:object];
  88.     NSArray *classProperties = [entity classProperties];
  89.     NSArray *relationships = [entity relationships];
  90.     int i,count = [relationships count];
  91.  
  92.     for(i=0; i<count; i++) {
  93.         EORelationship *relationship = [relationships objectAtIndex:i];
  94.  
  95.         if ([classProperties indexOfObjectIdenticalTo:relationship] != NSNotFound) {
  96.             NSArray *joins = [relationship joins];
  97.             int j, jcount = [joins count];
  98.  
  99.             for (j = 0; j < jcount; j++) {
  100.                 EOJoin *join = [joins objectAtIndex:j];
  101.                 if ([attributes indexOfObjectIdenticalTo:[join sourceAttribute]] != NSNotFound) {
  102.                     [affectedRelationships addObject:relationship];
  103.                     break;
  104.                 }
  105.             }
  106.         }
  107.     }
  108.  
  109.     // We now have a list of affected relationships that we need to retarget
  110.     {
  111.         count = [affectedRelationships count];
  112.         for(i=0; i<count; i++) {
  113.             EORelationship *relationship = [relationships objectAtIndex:i];
  114.             id dest = [self destinationObjectForRelationship:relationship sourceObject:object];
  115.             [object takeValue:dest forKey:[relationship name]];
  116.         }
  117.     }
  118. }
  119. @end
  120.